home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet multimedia / Muzyka / Edytory sampli (probek dzwieku) / ZynAddSubFX_2.2.0 / Setup_ZynAddSubFX-2.2.0.exe / source code / Seq / MIDIFile.C < prev    next >
C/C++ Source or Header  |  2005-03-14  |  9KB  |  390 lines

  1. /*
  2.   ZynAddSubFX - a software synthesizer
  3.  
  4.   MIDIFile.C - MIDI file loader
  5.   Copyright (C) 2003-2005 Nasca Octavian Paul
  6.   Author: Nasca Octavian Paul
  7.  
  8.   This program is free software; you can redistribute it and/or modify
  9.   it under the terms of version 2 of the GNU General Public License 
  10.   as published by the Free Software Foundation.
  11.  
  12.   This program is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License (version 2) for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License (version 2)
  18.   along with this program; if not, write to the Free Software Foundation,
  19.   Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  20.  
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "MIDIFile.h"
  26.  
  27.  
  28. MIDIFile::MIDIFile(){
  29.     midifile=NULL;
  30.     midifilesize=0;
  31.     midifilek=0;
  32.     midieof=false;
  33.     me=NULL;
  34. };
  35.  
  36. MIDIFile::~MIDIFile(){
  37.     clearmidifile();
  38. };
  39.  
  40. int MIDIFile::loadfile(char *filename){
  41.     clearmidifile();
  42.     
  43.     FILE *file=fopen(filename,"r");
  44.     if (file==NULL) return(-1);
  45.     
  46.     char header[4];
  47.     ZERO(header,4);
  48.     fread(header,4,1,file);
  49.  
  50.     //test to see if this a midi file
  51.     if ((header[0]!='M')||(header[1]!='T')||(header[2]!='h')||(header[3]!='d')){
  52.     fclose(file);
  53.     return(-1);
  54.     };
  55.     
  56.     //get the filesize
  57.     fseek(file,0,SEEK_END);
  58.     midifilesize=ftell(file);
  59.     rewind(file);
  60.     
  61.     midifile=new unsigned char[midifilesize];
  62.     ZERO(midifile,midifilesize);
  63.     fread(midifile,midifilesize,1,file);
  64.     fclose(file);
  65.  
  66. //    for (int i=0;i<midifilesize;i++) printf("%2x ",midifile[i]);
  67. //    printf("\n");
  68.     
  69.     
  70.     return(0);
  71. };
  72.  
  73. int MIDIFile::parsemidifile(MIDIEvents *me_){
  74.     this->me=me_;
  75.  
  76.     //read the header
  77.     int chunk=getint32();//MThd
  78.     if (chunk!=0x4d546864) return(-1);
  79.     int size=getint32();
  80.     if (size!=6) return(-1);//header is always 6 bytes long
  81.  
  82.  
  83.     int format=getint16();
  84.     printf("format %d\n",format);
  85.  
  86.     int ntracks=getint16();//this is always 1 if the format is "0"
  87.     printf("ntracks %d\n",ntracks);
  88.  
  89.     int division=getint16();
  90.     printf("division %d\n",division);
  91.     if (division>=0){//delta time units in each a quater note
  92. //    tick=???;
  93.     } else {//SMPTE (frames/second and ticks/frame)
  94.     printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet.");
  95.     };    
  96.     
  97.     if (ntracks>=NUM_MIDI_TRACKS) ntracks=NUM_MIDI_TRACKS-1;
  98.     
  99.     for (int n=0;n<ntracks;n++){
  100.     if (parsetrack(n)<0) {
  101.         clearmidifile();
  102.         return(-1);
  103.     };
  104.     };
  105.  
  106.     printf("\n\nCURRENT File position is = 0x%x\n",midifilek);
  107.     printf("\nMIDI file succesfully parsed.\n");
  108. //    printf("\n0x%x\n",getbyte());
  109.  
  110.     this->me=NULL;
  111.     return(0);
  112. };
  113.  
  114. //private members
  115.  
  116.  
  117. int MIDIFile::parsetrack(int ntrack){
  118.     printf("\n--==*Reading track %d **==--\n",ntrack);
  119.  
  120.     int chunk=getint32();//MTrk
  121.     if (chunk!=0x4d54726b) return(-1);
  122.  
  123.     int size=getint32();
  124.     printf("size = %d\n",size);
  125.  
  126.     int oldmidifilek=midifilek;
  127.  
  128.     unsigned char lastmsg=0;
  129.     unsigned int dt=0;
  130.     
  131.     while(!midieof){
  132.     unsigned int msgdeltatime=getvarint32();
  133.     
  134. ///    printf("MSGDELTATIME = %d\n",msgdeltatime);
  135.     
  136. //    dt+=msgdeltatime;
  137.  
  138.     int msg=peekbyte();
  139. ///    printf("raw msg=0x%x     ",msg);
  140.     if (msg<0x80) {
  141.         msg=lastmsg;
  142.     } else {
  143.         lastmsg=msg;
  144.         getbyte();
  145.     };  
  146. ///    printf("msg=0x%x\n",msg);
  147.  
  148. //    dt+=msgdeltatime;
  149.     add_dt(ntrack, msgdeltatime);
  150.     
  151.     unsigned int mtype,mlength;
  152.     
  153.     switch(msg){
  154.         case 0x80 ... 0x8f://note on off
  155.             parsenoteoff(ntrack,msg & 0x0f,dt);
  156.             dt=0;
  157.         break;
  158.         case 0x90 ... 0x9f://note on (or note off)
  159.             parsenoteon(ntrack,msg & 0x0f,dt);
  160.             dt=0;
  161.         break;
  162.         case 0xa0 ... 0xaf://aftertouch - ignored
  163.             skipnbytes(2);
  164.         break;
  165.         case 0xb0 ... 0xbf://control change
  166.             parsecontrolchange(ntrack,msg & 0x0f,dt);
  167.             dt=0;
  168.         break;
  169.         case 0xc0 ... 0xcf://program change - ignored
  170.             skipnbytes(1);
  171.         break;
  172.         case 0xd0 ... 0xdf://channel pressure - ignored
  173.             skipnbytes(1);
  174.         break;
  175.         case 0xe0 ... 0xef://channel mode messages
  176.             skipnbytes(2);
  177.         break;
  178.         case 0xf0://sysex - ignored
  179.         while (getbyte()!=0xf7){
  180.             if (midieof) break;
  181.         };
  182.           break;
  183.         case 0xf7://sysex (another type) - ignored
  184.         skipnbytes(getvarint32());
  185.           break;
  186.  
  187.         case 0xff://meta-event
  188.         mtype=getbyte();
  189.         mlength=getbyte();
  190.         parsemetaevent(mtype,mlength);
  191.             break;
  192.  
  193.         default:
  194.         getbyte();
  195.         printf("UNKNOWN message! 0x%x\n",msg);
  196.         return(-1);
  197.            break;
  198.     };
  199.  
  200.  
  201.     
  202.     if (midieof) return(-1);
  203.  
  204.     if ((midifilek-oldmidifilek)==size) break;
  205.         else if((midifilek-oldmidifilek)>size) return(-1);
  206. //    if (size!=6) return(-1);//header is always 6 bytes long
  207.     };
  208.  
  209.     printf("End Track\n\n");
  210.  
  211.     return(0);
  212. };
  213.  
  214.  
  215. void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt){
  216.     unsigned char note;
  217.     note=getbyte();
  218.     
  219.     unsigned char noteoff_velocity=getbyte();//unused by zynaddsubfx
  220.     noteoff_velocity=0;
  221.     if (chan>=NUM_MIDI_CHANNELS) return;
  222.     
  223.     me->tmpevent.deltatime=convertdt(dt);
  224.     me->tmpevent.type=1;
  225.     me->tmpevent.par1=note;
  226.     me->tmpevent.par2=0;
  227.     me->tmpevent.channel=chan;
  228.     
  229.     printf("Note off:%d \n",note);
  230.     
  231.     ///test 
  232. //    ntrack=0;
  233.     
  234.     me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent);
  235.     
  236. };
  237.  
  238.  
  239. void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){
  240.     unsigned char note,vel;
  241.     note=getbyte();
  242.     vel=getbyte();
  243.     
  244. //    printf("ntrack=%d\n",ntrack);
  245.     printf("[dt %d ]  Note on:%d %d\n",dt,note,vel);
  246.     
  247.     if (chan>=NUM_MIDI_CHANNELS) return;
  248.     
  249.     me->tmpevent.deltatime=convertdt(dt);
  250.     me->tmpevent.type=1;
  251.     me->tmpevent.par1=note;
  252.     me->tmpevent.par2=vel;
  253.     me->tmpevent.channel=chan;
  254.     me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent);
  255.  
  256.     
  257.     
  258. };
  259.  
  260. void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt){
  261.     unsigned char control,value;
  262.     control=getbyte();
  263.     value=getbyte();
  264.     
  265.     if (chan>=NUM_MIDI_CHANNELS) return;
  266.     
  267.     printf("[dt %d] Control change:%d %d\n",dt,control,value);
  268.     
  269.     me->tmpevent.deltatime=convertdt(dt);
  270.     me->tmpevent.type=2;
  271.     me->tmpevent.par1=control;//???????????? ma uit la Sequencer::recordnote() din varianele vechi de zyn
  272.     me->tmpevent.par2=value;
  273.     me->tmpevent.channel=chan;
  274.     me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent);
  275.     
  276. };
  277.  
  278. void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt){
  279.     unsigned char valhi,vallo;
  280.     vallo=getbyte();
  281.     valhi=getbyte();
  282.     
  283.     if (chan>=NUM_MIDI_CHANNELS) return;
  284.     
  285.     int value=(int)valhi*128+vallo;
  286.     
  287.     printf("[dt %d] Pitch wheel:%d\n",dt,value);
  288.     
  289. };
  290.  
  291. void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength){
  292.     int oldmidifilek=midifilek;
  293.     printf("meta-event type=0x%x  length=%d\n",mtype,mlength);
  294.     
  295.  
  296.  
  297.     midifilek=oldmidifilek+mlength;
  298.         
  299. };
  300.  
  301. void MIDIFile::add_dt(char ntrack, unsigned int dt){
  302.     me->tmpevent.deltatime=convertdt(dt);
  303.     me->tmpevent.type=255;
  304.     me->tmpevent.par1=0;
  305.     me->tmpevent.par2=0;
  306.     me->tmpevent.channel=0;
  307.     me->writeevent(&me->miditrack[(int)ntrack].record,&me->tmpevent);
  308. };
  309.  
  310.  
  311. unsigned int MIDIFile::convertdt(unsigned int dt){
  312.     double result=dt;
  313.     printf("DT=%d\n",dt);
  314.  
  315.     return((int) (result*15.0));
  316. };
  317.  
  318.  
  319. void MIDIFile::clearmidifile(){
  320.     if (midifile!=NULL) delete(midifile);
  321.     midifile=NULL;
  322.     midifilesize=0;
  323.     midifilek=0;
  324.     midieof=false;
  325.     data.tick=0.05;
  326. };
  327.  
  328. unsigned char MIDIFile::getbyte(){
  329.     if (midifilek>=midifilesize) {
  330.     midieof=true;
  331.     return(0);
  332.     };
  333.  
  334. ///    printf("(%d) ",midifile[midifilek]);
  335.     return(midifile[midifilek++]);
  336. };
  337.  
  338. unsigned char MIDIFile::peekbyte(){
  339.     if (midifilek>=midifilesize) {
  340.     midieof=true;
  341.     return(0);
  342.     };
  343.     return(midifile[midifilek]);
  344. };
  345.  
  346. unsigned int MIDIFile::getint32(){
  347.     unsigned int result=0;
  348.     for (int i=0;i<4;i++) {
  349.     result=result*256+getbyte();
  350.     };
  351.     if (midieof) result=0;
  352.     return(result);
  353. };
  354.  
  355. unsigned short int MIDIFile::getint16(){
  356.     unsigned short int result=0;
  357.     for (int i=0;i<2;i++) {
  358.     result=result*256+getbyte();
  359.     };
  360.     if (midieof) result=0;
  361.     return(result);
  362. };
  363.  
  364. unsigned int MIDIFile::getvarint32(){
  365.     unsigned long result=0;
  366.     unsigned char b;
  367.  
  368. ///    printf("\n[start]");
  369.  
  370.     if ((result = getbyte()) & 0x80) {
  371.         result &= 0x7f;
  372.         do  {
  373.         b=getbyte();
  374.             result = (result << 7) + (b & 0x7f);
  375.         }while (b & 0x80);
  376.     }
  377. ///    printf("[end - result= %d]\n",result);
  378.     return result;
  379. };
  380.  
  381.  
  382. void MIDIFile::skipnbytes(int n){
  383.     midifilek+=n;
  384.     if (midifilek>=midifilesize){
  385.     midifilek=midifilesize-1;
  386.     midieof=true;
  387.     };
  388. };
  389.  
  390.